前言

上一篇 dayjs 源码解析(四)(Dayjs 类)介绍了 dayjs 的源码目录结构。接下来,本篇将分析一下 dayjs 中插件功能的用法、源码以及如何编写自己的 dayjs 插件。

dayjs 插件用法

dayjs 的插件,通过挂载到 dayjs 函数下的 extend 函数加载,然后使用:

import plugin // 导入插件
dayjs.extend(plugin) // 加载插件
dayjs.extend(plugin, options) // 或者加载插件的同时,加入插件所需要的参数

例子:使用官方的 IsLeapYear 插件

import isLeapYear from 'dayjs/plugin/isLeapYear'

dayjs.extend(isLeapYear)

dayjs('2000-01-01').isLeapYear() // true

这就是 dayjs 插件的使用方法。

dayjs 插件源码(即 dayjs.extend() 方法)

// 扩展插件的方法
// plugin:插件函数
// option:插件的选项
dayjs.extend = (plugin, option) => {
  // 插件函数接受三个参数
  // 1.插件选项 2.Dayjs 类 3.dayjs 函数
  // 插件的方法都是挂载在 Dayjs 类的原型对象上的(Dayjs.prototype)。
  plugin(option, Dayjs, dayjs)
  return dayjs
}

dayjs.extend() 方法,接受两个参数,即插件(函数)和插件的选项。

在 dayjs.extend() 方法中,直接调用传入的插件(函数),且传入三个参数:传入 dayjs.extend() 方法的 option、Dayjs 类以及 dayjs 函数。

最后,返回 dayjs 函数。

然后,我们来看一个官方的 isLeapYear 插件的源码,看看它是怎么写的:

export default (o, c) => {
  const proto = c.prototype
  proto.isLeapYear = function () {
    return ((this.$y % 4 === 0) && (this.$y % 100 !== 0)) || (this.$y % 400 === 0)
  }
}

在 isLeapYear 插件源码中,导出一个函数,该函数接受两个参数(即在 dayjs.extend() 方法中的 option 和 Dayjs 类),然后将 isLeapYear 函数挂载到 Dayjs 类的原型对象上。因此,每个 Dayjs 实例都可以使用 isLeapYear 方法。

编写自己的 dayjs 插件

通过阅读插件的源码,我们知道了插件的方法,可以挂载到 Dayjs 类上、Dayjs 类原型上以及 dayjs 函数对象上。并且,可以通过插件选项(option),来对插件进行配置。
官方文档也提供了插件开发的模板:

export default (option, dayjsClass, dayjsFactory) => {
  // 扩展 dayjs() 实例
  // 例:添加 dayjs().isSameOrBefore() 实例方法
  dayjsClass.prototype.isSameOrBefore = function (arguments) {}

  // 扩展 dayjs 类
  // 例:添加 dayjs.utc() 类方法
  dayjsFactory.utc = (arguments) => {}

  // 覆盖已存在的 API
  // 例:扩展 dayjs().format() 方法
  const oldFormat = dayjsClass.prototype.format
  dayjsClass.prototype.format = function (arguments) {
    // 原始format结果
    const result = oldFormat(arguments)
    // 返回修改后结果
  }
}

通过插件,可以很方便的进行 dayjs 库的方法的扩展,来更好的服务我们的具体的业务需求。

dayjs 源码解析完。这五篇文章,也只是大概的解析了一下 dayjs 源码的主要函数、方法和类,其他 api 方法还需要自己一个一个去看。☺

总结

如何阅读源码?

  • 先从库的 api 入手,看其如何使用
  • 然后再看源码的入口函数或类,了解源码的整体结构
  • 最后再具体看 api 的源码

hileix
246 声望16 粉丝